/*
 * Copyright (C) 2021 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the
 *       distribution.
 *    3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
 *       its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#ifdef CONFIG_BLEHOST
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#include "ohos_bt_def.h"
#include "ohos_bt_gatt.h"
#include "ohos_bt_gatt_server.h"

#include "framework/bt_ctrl.h"

#include <bluetooth/bluetooth.h>
#include <bluetooth/gap.h>
#include <bluetooth/uuid.h>
#include <bluetooth/gatt.h>
#include <settings/settings.h>
// #include <bluetooth/conn_internal.h>

#include "bluetooth/conn.h"

#include "xr_ohos_utils.h"

/*============================================================================*
 *							  Constants
 *============================================================================*/

/** @brief  Config APP LE link number */
// #ifndef UPLUS_BLE_MAX_USERS
// #define UPLUS_BLE_MAX_USERS 5
// #endif

// static uint16_t aw_bt_mtu = 512;
// extern uplus_s32 xr_sys_debug_printf(const uplus_s8 *fmt, ...);
#define xr_sys_debug_printf(format, ...)                                       \
	do {                                                                   \
		printf("\033[1;34m" format "\033[0m", ##__VA_ARGS__);          \
	} while (0)
// #define xr_sys_debug_printf(format, ...)
#define OHOS_FUNCTION_NOT_IMPLEMENT                                            \
	{                                                                      \
		xr_sys_debug_printf("[%s][%d]:function not implement\r\n",     \
				    __func__, __LINE__);                       \
		return 0;                                                      \
	}

/*============================================================================*
 *							  Dyanmic DB SUPPORT
 *============================================================================*/

/** @brief  UUID */
static struct bt_uuid_16 *bt_uuid_gatt_primary; //BT_UUID_GATT_PRIMARY 0x2800
static struct bt_uuid_16 *bt_uuid_gatt_secondary; //BT_UUID_GATT_SECONDARY 0x2801
static struct bt_uuid_16 *bt_uuid_gatt_include; //BT_UUID_GATT_SECONDARY 0x2801
static struct bt_uuid_16 *bt_uuid_gatt_chrc; //BT_UUID_GATT_CHRC 0x2803
static struct bt_uuid_16 *bt_uuid_gatt_cep; //BT_UUID_GATT_CEP 0x2900
static struct bt_uuid_16 *bt_uuid_gatt_cud; //BT_UUID_GATT_CUD 0x2901
static struct bt_uuid_16 *bt_uuid_gatt_ccc; //BT_UUID_GATT_CCC 0x2902
static struct bt_uuid_16 *bt_uuid_gatt_cpf; //BT_UUID_GATT_CPF 0x2904
// static struct bt_uuid_16 *bt_uuid_gatt_scc; 		//BT_UUID_GATT_CCC 0x2903
// static struct bt_uuid_16 *bt_uuid_gatt_caf; 		//BT_UUID_GATT_CCC 0x2905
// other while use

// 16 bit
// 0000xxxx-0000-1000-8000-00805F9B34FB
// 32 bit
// xxxxxxxx-0000-1000-8000-00805F9B34FB

// UUID_MALLOC
static int BT_GATT_INIT_UUID_16(struct bt_uuid_16 **p_uuid, uint16_t uuid_vel)
{
	if (*p_uuid != NULL) {
		return -1;
	}
	*p_uuid = (struct bt_uuid_16 *)malloc(sizeof(struct bt_uuid_16));
	if (*p_uuid == NULL) {
		return -1;
	}
	(*p_uuid)->uuid.type = BT_UUID_TYPE_16;
	(*p_uuid)->val = uuid_vel;
	return 0;
}

static int BT_GATT_DEINIT_UUID_16(struct bt_uuid_16 **p_uuid)
{
	if (*p_uuid != NULL) {
		free(*p_uuid);
		*p_uuid = NULL;
	}
	return 0;
}
// UUID END
/** @brief  GATT */
#define BT_GATT_ATTRIBUTE_D(_attr, _uuid, _perm, _read, _write, _value)        \
	{                                                                      \
		_attr.uuid = _uuid;                                            \
		_attr.read = _read;                                            \
		_attr.write = _write;                                          \
		_attr.user_data = _value;                                      \
		_attr.handle = 0;                                              \
		_attr.perm = _perm;                                            \
	}

#define BT_GATT_PRIMARY_SERVICE_D(_attr, _service, _p_service_uuid)            \
	{                                                                      \
		struct bt_uuid *p_uuid = NULL;                                 \
		if (_p_service_uuid != NULL) {                                 \
			p_uuid = _p_service_uuid;                              \
		} else {                                                       \
			BT_GATT_INIT_UUID_16(&p_uuid, _service);               \
		}                                                              \
		BT_GATT_ATTRIBUTE_D(                                           \
			_attr, ((struct bt_uuid *)(bt_uuid_gatt_primary)),     \
			BT_GATT_PERM_READ, bt_gatt_attr_read_service, NULL,    \
			p_uuid)                                                \
	}

#define BT_GATT_SECONDARY_SERVICE_D(_attr, _service, _p_service_uuid)          \
	{                                                                      \
		struct bt_uuid *p_uuid = NULL;                                 \
		if (_p_service_uuid != NULL) {                                 \
			p_uuid = _p_service_uuid;                              \
		} else {                                                       \
			BT_GATT_INIT_UUID_16(&p_uuid, _service);               \
		}                                                              \
		BT_GATT_ATTRIBUTE_D(                                           \
			_attr, ((struct bt_uuid *)(bt_uuid_gatt_secondary)),   \
			BT_GATT_PERM_READ, bt_gatt_attr_read_service, NULL,    \
			p_uuid)                                                \
	}

#define BT_GATT_INCLUDE_SERVICE_D(_attr, _service_incl, _p_service_incl_uuid)  \
	{                                                                      \
		struct bt_uuid *p_uuid = NULL;                                 \
		if (_p_service_incl_uuid != NULL) {                            \
			p_uuid = _p_service_incl_uuid;                         \
		} else {                                                       \
			BT_GATT_INIT_UUID_16(&p_uuid, _service_incl);          \
		}                                                              \
		BT_GATT_ATTRIBUTE_D(                                           \
			_attr, ((struct bt_uuid *)(bt_uuid_gatt_include)),     \
			BT_GATT_PERM_READ, bt_gatt_attr_read_included, NULL,   \
			p_uuid)                                                \
	}

#define BT_GATT_CHRC_INIT_D(_chrc, _uuid, _props)                              \
	{                                                                      \
		_chrc = (struct bt_gatt_chrc *)malloc(                         \
			sizeof(struct bt_gatt_chrc));                          \
		_chrc->uuid = (struct bt_uuid *)_uuid;                         \
		_chrc->value_handle = 0U;                                      \
		_chrc->properties = _props;                                    \
	}

#define BT_GATT_CHARACTERISTIC_D(_attr0, _attr1, _uuid, _props, _perm, _read,  \
				 _write, _value, _p_attr_uuid)                 \
	{                                                                      \
		struct bt_uuid_16 *p_uuid = NULL;                              \
		if (_p_attr_uuid != NULL) {                                    \
			p_uuid = _p_attr_uuid;                                 \
		} else {                                                       \
			BT_GATT_INIT_UUID_16(&p_uuid, _uuid);                  \
		}                                                              \
		struct bt_gatt_chrc *p_chrc = NULL;                            \
		BT_GATT_CHRC_INIT_D(p_chrc, p_uuid, _props);                   \
		BT_GATT_ATTRIBUTE_D(_attr0,                                    \
				    ((struct bt_uuid *)(bt_uuid_gatt_chrc)),   \
				    BT_GATT_PERM_READ, bt_gatt_attr_read_chrc, \
				    NULL, (p_chrc));                           \
		BT_GATT_ATTRIBUTE_D(_attr1, ((struct bt_uuid *)(p_uuid)),      \
				    _perm, _read, _write, _value);             \
	}

//todo free and init
#define BT_GATT_CEP_D(_attr, _value)                                           \
	BT_GATT_ATTRIBUTE_D(_attr, ((struct bt_uuid *)(bt_uuid_gatt_cep)),     \
			    BT_GATT_PERM_READ, bt_gatt_attr_read_cep, NULL,    \
			    ((void *)_value))

#define BT_GATT_CUD_D(_attr, _value, _perm)                                    \
	BT_GATT_ATTRIBUTE_D(_attr, ((struct bt_uuid *)bt_uuid_gatt_cud),       \
			    _perm, bt_gatt_attr_read_cud, NULL,                \
			    (void *)_value)

#if 0
#define BT_GATT_MAX_CCC_NUM (10)
struct bt_gatt_ccc_cfg _ccc_cfg[BT_GATT_MAX_CCC_NUM][BT_GATT_CCC_MAX];
static int ccc_num = 0;
#endif

#define BT_GATT_CCC_MANAGED_D(_attr, _ccc, _perm)                              \
	BT_GATT_ATTRIBUTE_D(_attr, ((struct bt_uuid *)bt_uuid_gatt_ccc),       \
			    _perm, bt_gatt_attr_read_ccc,                      \
			    bt_gatt_attr_write_ccc, _ccc)

#define BT_GATT_CCC_INITIALIZER_D(p_ccc_m, _changed, _write, _match)           \
	{                                                                      \
		p_ccc_m = (struct _bt_gatt_ccc *)malloc(                       \
			sizeof(struct _bt_gatt_ccc));                          \
		/* p_ccc_m->cfg = _ccc_cfg[ccc_num]; */                        \
		/* ccc_num++; */                                               \
		p_ccc_m->cfg_changed = _changed;                               \
		p_ccc_m->cfg_write = _write;                                   \
		p_ccc_m->cfg_match = _match;                                   \
	}

#define BT_GATT_CCC_D(_attr, _changed, _perm)                                  \
	struct _bt_gatt_ccc *p_ccc_m = NULL;                                   \
	BT_GATT_CCC_INITIALIZER_D(p_ccc_m, _changed, NULL, NULL);              \
	BT_GATT_CCC_MANAGED_D(_attr, p_ccc_m, _perm)

//todo free and init
#define BT_GATT_CPF_D(_attr, _value)                                           \
	BT_GATT_ATTRIBUTE_D(_attr, bt_uuid_gatt_cpf, BT_GATT_PERM_READ,        \
			    bt_gatt_attr_read_cpf, NULL, (void *)_value)

#if 0
/*
#define BT_GATT_CAF(_value)						\
	BT_GATT_ATTRIBUTE(BT_UUID_GATT_CAF, BT_GATT_PERM_READ,		\
			  bt_gatt_attr_read_caf, NULL, _value)
*/
#endif

// GATT END
/** @brief  DATABASE */
#define VEDN_BLE_MAX_GATT_SRV_SIZE (5)
#define VEDN_BLE_MAX_GATT_CHAR_SIZE (40)
static struct bt_gatt_service_db {
	struct bt_gatt_service *srvs;
	int srv_count;
} g_gatt_srv_db; //全局变量保存database

static int ble_hal_database_init(void)
{
	if (g_gatt_srv_db.srvs != NULL) {
		return -1;
	}
	g_gatt_srv_db.srvs = (struct bt_gatt_service *)malloc(
		VEDN_BLE_MAX_GATT_SRV_SIZE * sizeof(struct bt_gatt_service));
	g_gatt_srv_db.srv_count = 0;
	if (g_gatt_srv_db.srvs == NULL) {
		return -1;
	}
	return 0;
}

#define BT_GATT_MAX_SIZE_DATA (32)
static void cccd_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value);
static ssize_t write_att_cb(struct bt_conn *conn,
			    const struct bt_gatt_attr *attr, const void *buf,
			    uint16_t len, uint16_t offset, uint8_t flags);
static ssize_t read_att_cb(struct bt_conn *conn,
			   const struct bt_gatt_attr *attr, void *buf,
			   uint16_t len, uint16_t offset);

// static void *ble_hal_add_svc(uint16_t _uuid16, int _srv_type)
// {
// 	struct bt_gatt_service *vnd_svc = &(g_gatt_srv_db.srvs[g_gatt_srv_db.srv_count]);
// 	g_gatt_srv_db.srv_count++;
// 	//  = (struct bt_gatt_service *)malloc(sizeof(struct bt_gatt_service));
// 	struct bt_gatt_attr *vnd_attrs = (struct bt_gatt_attr *)malloc(VEDN_BLE_MAX_GATT_CHAR_SIZE * sizeof(struct bt_gatt_attr));
// 	if (_srv_type == 0) {
// 		BT_GATT_PRIMARY_SERVICE_D(((vnd_attrs[0])), _uuid16);
// 	} else if (_srv_type == 1) {
// 		BT_GATT_SECONDARY_SERVICE_D(((vnd_attrs[0])), _uuid16);
// 	}
// 	vnd_svc->attrs = vnd_attrs;
// 	vnd_svc->attr_count += 1;
// 	return (void *)vnd_svc;
// }

// static int32_t ble_hal_add_chr(void *p_svc, uint16_t uuid16, uint8_t properties, uint16_t val_perms, void *read, void *write)
// {
// 	struct bt_gatt_service *vnd_svc = ((struct bt_gatt_service *)p_svc);
// 	BT_GATT_CHARACTERISTIC_D((vnd_svc->attrs)[vnd_svc->attr_count], (vnd_svc->attrs)[vnd_svc->attr_count + 1],
// 	uuid16, properties, val_perms, read, write, malloc(sizeof(uint8_t) * BT_GATT_MAX_SIZE_DATA));
// 	vnd_svc->attr_count += 2;
// 	if (properties & 0x80) { //cep
// 		BT_GATT_CEP_D((vnd_svc->attrs)[vnd_svc->attr_count], malloc(sizeof(uint8_t) * BT_GATT_MAX_SIZE_DATA));
// 		vnd_svc->attr_count += 1;
// 	}
// 	if (properties & 0x10) { //notify
// 		BT_GATT_CCC_D((vnd_svc->attrs)[vnd_svc->attr_count], cccd_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE);
// 		vnd_svc->attr_count += 1;
// 	}
// 	return 0;
// }

static int bt_gatt_uuid_init(void)
{
	BT_GATT_INIT_UUID_16(&bt_uuid_gatt_primary, 0x2800);
	BT_GATT_INIT_UUID_16(&bt_uuid_gatt_secondary, 0x2801);
	BT_GATT_INIT_UUID_16(&bt_uuid_gatt_include, 0x2802);
	BT_GATT_INIT_UUID_16(&bt_uuid_gatt_chrc, 0x2803);
	BT_GATT_INIT_UUID_16(&bt_uuid_gatt_cep, 0x2900);
	BT_GATT_INIT_UUID_16(&bt_uuid_gatt_cud, 0x2901);
	BT_GATT_INIT_UUID_16(&bt_uuid_gatt_ccc, 0x2902);
	BT_GATT_INIT_UUID_16(&bt_uuid_gatt_cpf, 0x2904);
	return 0;
}

static int bt_gatt_attr_deinit(struct bt_gatt_attr *vnd_attrs)
{
	if (vnd_attrs->uuid != NULL) {
		free((struct bt_uuid *)(vnd_attrs->uuid));
		vnd_attrs->uuid = NULL;
	}
	if (vnd_attrs->user_data != NULL) {
		free(vnd_attrs->user_data);
		vnd_attrs->user_data = NULL;
	}
	return 0;
}

static int bt_gatt_srv_deinit(struct bt_gatt_service *vnd_svc)
{
	if (vnd_svc == NULL || vnd_svc->attr_count - 1 <= 0) {
		return -1;
	}
	for (int i = 0; i < vnd_svc->attr_count - 1; i++) {
		bt_gatt_attr_deinit(&((vnd_svc->attrs)[i]));
	}
	if (vnd_svc->attrs != NULL) {
		free(vnd_svc->attrs);
		vnd_svc->attrs = NULL;
	}
	vnd_svc->attr_count = 0;
	return 0;
}

static int bt_gatt_database_deinit(void)
{
	for (int i = 0; i < g_gatt_srv_db.srv_count; i++) {
		bt_gatt_srv_deinit(&(g_gatt_srv_db.srvs[i]));
	}
	if (g_gatt_srv_db.srvs) {
		free(g_gatt_srv_db.srvs);
		g_gatt_srv_db.srvs = NULL;
		g_gatt_srv_db.srv_count = 0;
	}
	return 0;
}
/*============================================================================*
 *							  GATT UTILS
 *============================================================================*/
typedef struct uuid_attr_ {
	uint16_t uuid;
	struct bt_gatt_attr *vnd_attrs;
} uuid_attr_t;

static uint8_t uuid_to_pattr(const struct bt_gatt_attr *attr, uint16_t handle,
			     void *user_data)
{
	uuid_attr_t *uuid_attr = (uuid_attr_t *)user_data;
	if (!bt_uuid_cmp(attr->uuid, BT_UUID_DECLARE_16(uuid_attr->uuid))) {
		uuid_attr->vnd_attrs = (struct bt_gatt_attr *)attr;
		return BT_GATT_ITER_STOP;
	}
	return BT_GATT_ITER_CONTINUE;
}

static struct bt_gatt_attr *bt_gatt_uuid_to_pattr(uint16_t _uuid)
{
	uuid_attr_t uuid_attr;
	uuid_attr.uuid = _uuid;
	uuid_attr.vnd_attrs = NULL;

	bt_gatt_foreach_attr(0x0001, 0xffff, uuid_to_pattr, (void *)&uuid_attr);

	return uuid_attr.vnd_attrs;
}

typedef struct handle_attr_ {
	uint16_t handle;
	struct bt_gatt_attr *vnd_attrs;
} handle_attr_t;

static uint8_t handle_to_pattr(const struct bt_gatt_attr *attr, uint16_t handle,
			       void *user_data)
{
	handle_attr_t *uuid_attr = (handle_attr_t *)user_data;
	if (attr->handle == uuid_attr->handle) {
		uuid_attr->vnd_attrs = (struct bt_gatt_attr *)attr;
		return BT_GATT_ITER_STOP;
	}
	return BT_GATT_ITER_CONTINUE;
}

static struct bt_gatt_attr *bt_gatt_handle_to_pattr(uint16_t handle)
{
	handle_attr_t uuid_attr;
	uuid_attr.handle = handle;
	uuid_attr.vnd_attrs = NULL;

	bt_gatt_foreach_attr(handle, handle, handle_to_pattr,
			     (void *)&uuid_attr);

	return uuid_attr.vnd_attrs;
}

static uint8_t print_attr(const struct bt_gatt_attr *attr, uint16_t handle,
			  void *user_data)
{
	char str[BT_UUID_STR_LEN];

	bt_uuid_to_str(attr->uuid, str, sizeof(str));
	xr_sys_debug_printf("attr %p handle 0x%04x uuid %s perm 0x%02x\n", attr,
			    attr->handle, str, attr->perm);

	return BT_GATT_ITER_CONTINUE;
}

static int show_dynamic_db()
{
	struct bt_uuid_16 uuid;
	size_t total_len;
	void *data;

	xr_sys_debug_printf(
		"=================================================\n");
	bt_gatt_foreach_attr(0x0001, 0xffff, print_attr, (void *)data);
	xr_sys_debug_printf(
		"=================================================\n");

	return 0;
}
// DB END
// CONN START
static inline struct bt_conn *connid_to_conn(int conn_id)
{
	// return default_conn; //todo
}
static inline uint16_t conn_to_connid(struct bt_conn *conn)
{
	return 1;
	// return conn->handle;
}

// static inline struct bt_conn *connid_to_conn(uint16_t conn_handle)
// {
//	 return bt_conn_lookup_index((uint8_t)conn_handle);
// }
// static inline uint16_t conn_to_connid(struct bt_conn *conn)
// {
//	 return (uint16_t)bt_conn_index(conn);
//	 // return conn->handle;
// }
// CONN END
/*============================================================================*
 *							  OHOS GATT SUPPORT
 *============================================================================*/
static BtGattServerCallbacks xrble_hal_gattservercallback;

//todo CCC配置api
static void cccd_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	// uint8_t *data = 0;

	// uint8_t **pp_value = &data;
	// uint16_t  length = 0;
	// uint16_t  *p_length = &length;

	// conn_to_handle(default_conn);

	// xr_sys_debug_printf("%s,%d attr->handle = %d\r\n", __func__, __LINE__, attr->handle);

	// if (value) {
	// 	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	// 	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	// 	xr_sys_debug_printf("%s,%d %d \r\n", __func__, __LINE__, length);

	// 	if (length > 0) {
	// 		xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	// 		struct bt_gatt_attr *pattr_vel = bt_gatt_handle_to_pattr(attr->handle - 1);
	// 		xr_sys_debug_printf("%s,%d\n", __func__, __LINE__);
	// 		if (*pp_value != NULL) {
	// 			ble_hex_dump("cccc  ", 31, *pp_value, length);
	// 			bt_gatt_notify(default_conn, pattr_vel, *pp_value, length);
	// 		} else {
	// 			xr_sys_debug_printf("%s,%d\n", __func__, __LINE__);
	// 		}
	// 		if (NULL != *pp_value) {
	// 			free(*pp_value); //!!
	// 		}
	// 	}
	// 	else {
	// 		xr_sys_debug_printf("notify Error\n");
	// 		return;
	// 	}
	// }
}

static void indicate_att_cb(struct bt_conn *conn,
			    const struct bt_gatt_attr *attr, uint8_t err)
{
	xr_sys_debug_printf("Indication Callback\n");
}

static ssize_t write_att_cb(struct bt_conn *conn,
			    const struct bt_gatt_attr *attr, const void *buf,
			    uint16_t len, uint16_t offset, uint8_t flags)
{
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	struct bt_conn_info info;
	if (bt_conn_get_info(conn, &info) < 0) {
		// addr[0] = '\0';
		return;
	}
	BtReqWriteCbPara ohos_write_cb_param;

	ohos_write_cb_param.connId = conn_to_connid(conn);
	ohos_write_cb_param.transId = OHOS_BT_TRANSPORT_LE;
	XRBLE_ADDR_2_OHOS_ADDR(info.le.dst, ohos_write_cb_param.bdAddr);
	ohos_write_cb_param.attrHandle = attr->handle;
	ohos_write_cb_param.offset = offset;
	ohos_write_cb_param.length = len;
	ohos_write_cb_param.needRsp = true;
	ohos_write_cb_param.isPrep = false; //prepare write
	ohos_write_cb_param.value = buf;

	if (xrble_hal_gattservercallback.requestWriteCb) {
		xrble_hal_gattservercallback.requestWriteCb(
			ohos_write_cb_param);
	}

	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	return len;
}

static ssize_t read_att_cb(struct bt_conn *conn,
			   const struct bt_gatt_attr *attr, void *buf,
			   uint16_t len, uint16_t offset)
{
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	ssize_t ret;

	struct bt_conn_info info;
	if (bt_conn_get_info(conn, &info) < 0) {
		return -1;
	}
	BtReqReadCbPara ohos_read_cb_param;

	ohos_read_cb_param.connId = conn_to_connid(conn);
	ohos_read_cb_param.transId = OHOS_BT_TRANSPORT_LE;
	XRBLE_ADDR_2_OHOS_ADDR(info.le.dst, ohos_read_cb_param.bdAddr);
	ohos_read_cb_param.attrHandle = attr->handle;
	ohos_read_cb_param.offset = offset;
	ohos_read_cb_param.isLong = false; //todo

	if (xrble_hal_gattservercallback.requestReadCb) { //todo what????
		xrble_hal_gattservercallback.requestReadCb(ohos_read_cb_param);
	}

	// bt_gatt_attr_read(conn, attr, buf, len, offset, *pp_buf, 0); //todo
	return ret;
}
/*============================================================================*
 *							  OHOS GATT DB SUPPORT
 *============================================================================*/
//GATT UTILS
static int OHOS_UUID_TO_XR_UUID(BtUuid *ohos_uuid, struct bt_uuid **p_uuid)
{
	if (*p_uuid != NULL || ohos_uuid == NULL) {
		xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
		return -1;
	}

	switch (ohos_uuid->uuidLen) {
	case BT_UUID_SIZE_16:
		*p_uuid =
			(struct bt_uuid_16 *)malloc(sizeof(struct bt_uuid_16));
		if (*p_uuid == NULL) {
			return -2;
		}
		((struct bt_uuid_16 *)*p_uuid)->uuid.type = BT_UUID_TYPE_16;
		((struct bt_uuid_16 *)*p_uuid)->val =
			(uint16_t)(ohos_uuid->uuid[0]);
		return 0;
	case BT_UUID_SIZE_32:
		*p_uuid =
			(struct bt_uuid_32 *)malloc(sizeof(struct bt_uuid_32));
		if (*p_uuid == NULL) {
			return -2;
		}
		((struct bt_uuid_32 *)*p_uuid)->uuid.type = BT_UUID_TYPE_32;
		((struct bt_uuid_32 *)*p_uuid)->val =
			(uint32_t)(ohos_uuid->uuid[0]);
		return 0;
	case BT_UUID_SIZE_128:
		*p_uuid =
			(struct bt_uuid_32 *)malloc(sizeof(struct bt_uuid_32));
		if (*p_uuid == NULL) {
			return -2;
		}
		((struct bt_uuid_128 *)*p_uuid)->uuid.type = BT_UUID_TYPE_32;
		memcpy(((struct bt_uuid_128 *)*p_uuid)->val, ohos_uuid->uuid,
		       BT_UUID_SIZE_128);
		return 0;
	default:
		return -2;
	}
	return -3;
}

static int BT_GATT_DEINIT_UUID(struct bt_uuid **p_uuid)
{
	if (*p_uuid != NULL) {
		free(*p_uuid);
		*p_uuid = NULL;
	}
	return 0;
}
// UUID END
uint8_t OHOS_ATTR_PERM_TO_XR_ATTR_PERM(GattAttributePermission ohos_attr_perm)
{
	uint8_t xr_attr_perm = BT_GATT_PERM_NONE;
	switch (ohos_attr_perm) {
	case OHOS_GATT_PERMISSION_READ:
		xr_attr_perm |= BT_GATT_PERM_READ;
		xr_attr_perm |= BT_GATT_PERM_READ_ENCRYPT;
		xr_attr_perm |= BT_GATT_PERM_READ_AUTHEN;
		break;
	case OHOS_GATT_PERMISSION_READ_ENCRYPTED:
		xr_attr_perm |= BT_GATT_PERM_READ_ENCRYPT;
		break;
	case OHOS_GATT_PERMISSION_READ_ENCRYPTED_MITM:
		xr_attr_perm |= BT_GATT_PERM_READ_AUTHEN;
		break;
	case OHOS_GATT_PERMISSION_WRITE:
		xr_attr_perm |= BT_GATT_PERM_WRITE;
		xr_attr_perm |= BT_GATT_PERM_WRITE_ENCRYPT;
		xr_attr_perm |= BT_GATT_PERM_WRITE_AUTHEN;
		break;
	case OHOS_GATT_PERMISSION_WRITE_ENCRYPTED:
		xr_attr_perm |= BT_GATT_PERM_WRITE_ENCRYPT;
		break;
	case OHOS_GATT_PERMISSION_WRITE_ENCRYPTED_MITM:
		xr_attr_perm |= BT_GATT_PERM_WRITE_AUTHEN;
		break;
	case OHOS_GATT_PERMISSION_WRITE_SIGNED:
		//todo ext
		break;
	case OHOS_GATT_PERMISSION_WRITE_SIGNED_MITM:
		//todo ext
		break;
	default:
		break;
	}
	// BT_GATT_PERM_PREPARE_WRITE;
	return xr_attr_perm;
}

static inline struct bt_gatt_service *serverid_to_psrv(int serverid)
{
	void *psrv = (void *)(&g_gatt_srv_db.srvs[serverid]); //todo
	return (struct bt_gatt_service *)psrv;
}

static inline int psrv_to_serverid(void *p_srv)
{
	int srv_id;
	if (p_srv == NULL) {
		return -1;
	}
	srv_id = ((struct bt_gatt_service *)p_srv -
		  (struct bt_gatt_service *)(&g_gatt_srv_db.srvs[0])) /
		 sizeof(struct bt_gatt_service *);
	if (srv_id < 0 || srv_id >= VEDN_BLE_MAX_GATT_SRV_SIZE) {
		return -1;
	}

	return srv_id;
}

static int ble_hal_add_svc_with_server_id(int server_id, struct bt_uuid *p_uuid,
					  int is_primary, int num_attr_handle)
{
	uint16_t _uuid16;
	if (p_uuid == NULL) {
		return -1;
	}
	struct bt_gatt_service *vnd_svc = serverid_to_psrv(server_id);
	// struct bt_gatt_service *vnd_svc = &(g_gatt_srv_db.srvs[g_gatt_srv_db.srv_count]);
	g_gatt_srv_db.srv_count++;
	//  = (struct bt_gatt_service *)malloc(sizeof(struct bt_gatt_service));
	struct bt_gatt_attr *vnd_attrs = (struct bt_gatt_attr *)malloc(
		(VEDN_BLE_MAX_GATT_CHAR_SIZE > (num_attr_handle + 1) ?
			       VEDN_BLE_MAX_GATT_CHAR_SIZE :
			       (num_attr_handle + 1)) *
		sizeof(struct bt_gatt_attr));
	if (is_primary == 1) {
		BT_GATT_PRIMARY_SERVICE_D(((vnd_attrs[0])), _uuid16, p_uuid);
	} else if (is_primary == 0) {
		BT_GATT_SECONDARY_SERVICE_D(((vnd_attrs[0])), _uuid16, p_uuid);
	}
	vnd_svc->attrs = vnd_attrs;
	vnd_svc->attr_count += 1;
	return server_id;
}

static int ble_hal_add_include_svc_with_server_id(int server_id,
						  struct bt_uuid *p_uuid,
						  int num_attr_handle)
{
	return -1; //todo
		// uint16_t _uuid16;
		// if (p_uuid == NULL) {
		// 	return -1;
		// }
		// struct bt_gatt_service *vnd_svc = serverid_to_psrv(server_id);
		// // struct bt_gatt_service *vnd_svc = &(g_gatt_srv_db.srvs[g_gatt_srv_db.srv_count]);
		// g_gatt_srv_db.srv_count++;
		// //  = (struct bt_gatt_service *)malloc(sizeof(struct bt_gatt_service));
		// struct bt_gatt_attr *vnd_attrs = (struct bt_gatt_attr *)malloc((VEDN_BLE_MAX_GATT_CHAR_SIZE>(num_attr_handle+1)?VEDN_BLE_MAX_GATT_CHAR_SIZE:(num_attr_handle+1)) * sizeof(struct bt_gatt_attr));
		// BT_GATT_INCLUDE_SERVICE_D(((vnd_attrs[0])), _service_incl, _p_service_incl_uuid);
		// // BT_GATT_PRIMARY_SERVICE_D(((vnd_attrs[0])), _uuid16, p_uuid);
		// vnd_svc->attrs = vnd_attrs;
		// vnd_svc->attr_count += 1;
		// return server_id;
}

#define BT_GATT_MAX_SIZE_DATA (32)
static int ble_hal_add_chr_with_server_id(int server_id, struct bt_uuid *p_uuid,
					  uint8_t properties,
					  uint16_t val_perms, void *read,
					  void *write)
{
	uint16_t _uuid16;
	if (p_uuid == NULL) {
		return -1;
	}
	struct bt_gatt_service *vnd_svc = serverid_to_psrv(server_id);
	BT_GATT_CHARACTERISTIC_D(
		(vnd_svc->attrs)[vnd_svc->attr_count],
		(vnd_svc->attrs)[vnd_svc->attr_count + 1], _uuid16, properties,
		val_perms, read, write,
		malloc(sizeof(uint8_t) * BT_GATT_MAX_SIZE_DATA), p_uuid);
	vnd_svc->attr_count += 2;
	// if (properties & 0x80) { //cep
	// 	BT_GATT_CEP_D((vnd_svc->attrs)[vnd_svc->attr_count], malloc(sizeof(uint8_t) * BT_GATT_MAX_SIZE_DATA));
	// 	vnd_svc->attr_count += 1;
	// }
	// if (properties & 0x10) { //notify
	// 	BT_GATT_CCC_D((vnd_svc->attrs)[vnd_svc->attr_count], cccd_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE);
	// 	vnd_svc->attr_count += 1;
	// }
	return 0;
}

#if 1

int32_t ble_hal_add_cep(void *p_svc)
{
	struct bt_gatt_service *vnd_svc = ((struct bt_gatt_service *)p_svc);
	BT_GATT_CEP_D((vnd_svc->attrs)[vnd_svc->attr_count],
		      malloc(sizeof(uint8_t) * BT_GATT_MAX_SIZE_DATA));
	vnd_svc->attr_count += 1;
	return 0;
}

int32_t ble_hal_add_cud(void *p_svc, uint8_t perm) //todo
{
	struct bt_gatt_service *vnd_svc = ((struct bt_gatt_service *)p_svc);
	// uint8_t perm = OHOS_ATTR_PERM_TO_XR_ATTR_PERM(ohos_attr_perm);
	BT_GATT_CUD_D((vnd_svc->attrs)[vnd_svc->attr_count],
		      malloc(sizeof(uint8_t) * BT_GATT_MAX_SIZE_DATA), perm);
	vnd_svc->attr_count += 1;
	return 0;
}

int32_t ble_hal_add_ccc(void *p_svc, void *changed, uint8_t perm)
{
	struct bt_gatt_service *vnd_svc = ((struct bt_gatt_service *)p_svc);
	// if (properties & 0x30) { //CAE_BLE_HAL_CHR_EXT_PROP
	BT_GATT_CCC_D((vnd_svc->attrs)[vnd_svc->attr_count], changed, perm);
	vnd_svc->attr_count += 1;
	// }
	return 0;
}
int32_t ble_hal_add_cpf(void *p_svc)
{
	struct bt_gatt_service *vnd_svc = ((struct bt_gatt_service *)p_svc);
	BT_GATT_CPF_D((vnd_svc->attrs)[vnd_svc->attr_count],
		      malloc(sizeof(uint8_t) * BT_GATT_MAX_SIZE_DATA));
	vnd_svc->attr_count += 1;
	return 0;
}
#endif

/*============================================================================*
 *							  OHOS API SUPPORT
 *============================================================================*/
int bt_gatt_hal_init()
{
	bt_gatt_uuid_init();
	ble_hal_database_init();
}

int BleGattsRegister(BtUuid appUuid)
{
	OHOS_FUNCTION_NOT_IMPLEMENT
}
int BleGattsUnRegister(int serverId)
{
	OHOS_FUNCTION_NOT_IMPLEMENT
}
int BleGattsDisconnect(int serverId, BdAddr bdAddr, int connId)
{
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	int err;
	struct bt_conn *conn = bt_conn_ref(connid_to_conn(connId));

	if (!conn) {
		xr_sys_debug_printf("Not connected");
		return -ENOEXEC;
	}

	err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
	if (err) {
		xr_sys_debug_printf("Disconnection failed (err %d)", err);
		bt_conn_unref(conn);
		return err;
	}
	bt_conn_unref(conn);

	return 0;
}

int BleGattsAddService(int serverId, BtUuid srvcUuid, bool isPrimary,
		       int number)
{
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	struct bt_uuid *p_server_uuid = NULL;
	OHOS_UUID_TO_XR_UUID(&srvcUuid, &p_server_uuid);
	return ble_hal_add_svc_with_server_id(serverId, p_server_uuid,
					      isPrimary, number);
}

int BleGattsAddIncludedService(int serverId, int srvcHandle, int includedHandle)
{
	OHOS_FUNCTION_NOT_IMPLEMENT
}

int BleGattsAddCharacteristic(int serverId, int srvcHandle, BtUuid characUuid,
			      int properties, int permissions)
{
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	void *_read_cb = read_att_cb;
	void *_write_cb = write_att_cb;
	struct bt_uuid *p_attr_uuid = NULL;
	OHOS_UUID_TO_XR_UUID(&characUuid, &p_attr_uuid);
	return ble_hal_add_chr_with_server_id(serverId, p_attr_uuid, properties,
					      permissions, _read_cb, _write_cb);
}

int BleGattsAddDescriptor(int serverId, int srvcHandle, BtUuid descUuid,
			  int permissions)
{
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	struct bt_gatt_service *p_svc = serverid_to_psrv(serverId);
	struct bt_uuid *p_uuid = NULL;
	int err;
	uint8_t perm;
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	if (p_svc == NULL) {
		err = -1;
		goto failed;
	}
	err = OHOS_UUID_TO_XR_UUID(&descUuid, &p_uuid);
	if (err) {
		err = -1;
		goto failed;
	}
	perm = OHOS_ATTR_PERM_TO_XR_ATTR_PERM(permissions); //todo
	if (!bt_uuid_cmp(p_uuid, BT_UUID_GATT_CHRC)) {
		xr_sys_debug_printf("%s,%d what the api ???\r\n", __func__,
				    __LINE__);
		return -3;
	} else if (!bt_uuid_cmp(p_uuid, BT_UUID_GATT_CEP)) {
		err = ble_hal_add_cep(p_svc);
	} else if (!bt_uuid_cmp(p_uuid, BT_UUID_GATT_CUD)) {
		err = ble_hal_add_cud(p_svc, perm); //todo
	} else if (!bt_uuid_cmp(p_uuid, BT_UUID_GATT_CCC)) {
		err = ble_hal_add_ccc(p_svc, NULL,
				      perm); //todotodotodotodotodo ccc NULL
	} else if (!bt_uuid_cmp(p_uuid, BT_UUID_GATT_SCC)) {
		err = -2;
	} else if (!bt_uuid_cmp(p_uuid, BT_UUID_GATT_CPF)) {
		err = ble_hal_add_cpf(p_svc);
	} else if (!bt_uuid_cmp(p_uuid, BT_UUID_GATT_CAF)) {
		err = -2;
	}

failed:

	xr_sys_debug_printf("%s,%d add des faild %d\r\n", __func__, __LINE__,
			    err);
	return (err ? err : (0)); //todo
}

int BleGattsStartService(int serverId, int srvcHandle)
{
	OHOS_FUNCTION_NOT_IMPLEMENT
}
int BleGattsStopService(int serverId, int srvcHandle)
{
	OHOS_FUNCTION_NOT_IMPLEMENT
}
int BleGattsDeleteService(int serverId, int srvcHandle)
{
	OHOS_FUNCTION_NOT_IMPLEMENT
}
int BleGattsClearServices(int serverId)
{
	OHOS_FUNCTION_NOT_IMPLEMENT
}

int BleGattsSendResponse(int serverId, GattsSendRspParam *param)
{
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	struct bt_conn *now_conn = NULL;
	// struct bt_gatt_attr *vnd_attrs = NULL;
	// ohos_attr_id_to_pattr(param->attrHandle, vnd_attrs); //todo
	struct bt_gatt_attr *pattr_vel = NULL;
	pattr_vel = bt_gatt_handle_to_pattr((uint16_t)(param->attrHandle));
	if (pattr_vel == NULL) {
		return -1;
	}
	now_conn = connid_to_conn(param->connectId);
	if (now_conn == NULL) {
		return -1;
	}

	uint8_t *data = param->value;
	uint8_t status = param->status;
	int len = param->valueLen;
	int offset = 0;

	bt_gatt_attr_read(now_conn, pattr_vel, pattr_vel->user_data, len,
			  offset, data, len); //todo need test

	// while callback queue_wait()
	// gatt transfer struct
	// queue_give();
	//todo //todo //todo
	return 0;
}

static void notify_cb(struct bt_conn *conn, void *user_data)
{
	xr_sys_debug_printf("Nofication sent to conn %p", conn);
}
static void indicate_cb(struct bt_conn *conn,
			struct bt_gatt_indicate_params *params, uint8_t err)
{
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
}
int BleGattsSendIndication(int serverId, GattsSendIndParam *param)
{
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	struct bt_conn *now_conn = NULL;
	// struct bt_gatt_attr *vnd_attrs = NULL;
	// ohos_attr_id_to_pattr(param->attrHandle, vnd_attrs); //todo
	struct bt_gatt_attr *pattr_vel = NULL;
	pattr_vel = bt_gatt_handle_to_pattr((uint16_t)param->attrHandle);
	if (pattr_vel == NULL) {
		return -1;
	}

	now_conn = bt_conn_ref(connid_to_conn(param->connectId));
	uint8_t *data = param->value;
	uint8_t len = param->valueLen;
	if (param->confirm == 1) { //indicate
		struct bt_gatt_indicate_params indicate_params;
		memset(&indicate_params, 0, sizeof(indicate_params));

		indicate_params.uuid = pattr_vel->uuid;
		indicate_params.attr = pattr_vel;
		indicate_params.data = &data;
		indicate_params.len = len;
		indicate_params.func = indicate_cb;

		bt_gatt_indicate(NULL, &indicate_params);
	} else { //notify
		struct bt_gatt_notify_params notify_params;
		memset(&notify_params, 0, sizeof(notify_params));

		notify_params.uuid = pattr_vel->uuid;
		notify_params.attr = pattr_vel;
		notify_params.data = &data;
		notify_params.len = len;
		notify_params.func = notify_cb;
		notify_params.user_data = NULL;
		bt_gatt_notify_cb(NULL, &notify_params);
	}
	bt_conn_unref(now_conn);
	return 0;
}

int BleGattsSetEncryption(BdAddr bdAddr, BleSecAct secAct)
{
	OHOS_FUNCTION_NOT_IMPLEMENT
	//1 addr to conn
	//2 set securty

	// /** No encryption */
	// OHOS_BLE_SEC_NONE = 0x00,
	// /** Encryption */
	// OHOS_BLE_SEC_ENCRYPT,
	// /** Encryption without MITM */
	// OHOS_BLE_SEC_ENCRYPT_NO_MITM,
	// /** Encryption with MITM */
	// OHOS_BLE_SEC_ENCRYPT_MITM
	return 0;
}

int BleGattsRegisterCallbacks(BtGattServerCallbacks *func)
{
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	if (!func) {
		return -1;
	}
	if (func->registerServerCb) {
		xrble_hal_gattservercallback.registerServerCb =
			func->registerServerCb;
	}
	if (func->connectServerCb) {
		xrble_hal_gattservercallback.connectServerCb =
			func->connectServerCb;
	}
	if (func->disconnectServerCb) {
		xrble_hal_gattservercallback.disconnectServerCb =
			func->disconnectServerCb;
	}
	if (func->serviceAddCb) {
		xrble_hal_gattservercallback.serviceAddCb = func->serviceAddCb;
	}
	if (func->includeServiceAddCb) {
		xrble_hal_gattservercallback.includeServiceAddCb =
			func->includeServiceAddCb;
	}
	if (func->characteristicAddCb) {
		xrble_hal_gattservercallback.characteristicAddCb =
			func->characteristicAddCb;
	}
	if (func->descriptorAddCb) {
		xrble_hal_gattservercallback.descriptorAddCb =
			func->descriptorAddCb;
	}
	if (func->serviceStartCb) {
		xrble_hal_gattservercallback.serviceStartCb =
			func->serviceStartCb;
	}
	if (func->serviceStopCb) {
		xrble_hal_gattservercallback.serviceStopCb =
			func->serviceStopCb;
	}
	if (func->serviceDeleteCb) {
		xrble_hal_gattservercallback.serviceDeleteCb =
			func->serviceDeleteCb;
	}
	if (func->requestReadCb) {
		xrble_hal_gattservercallback.requestReadCb =
			func->requestReadCb;
	}
	if (func->requestWriteCb) {
		xrble_hal_gattservercallback.requestWriteCb =
			func->requestWriteCb;
	}
	if (func->responseConfirmationCb) {
		xrble_hal_gattservercallback.responseConfirmationCb =
			func->responseConfirmationCb;
	}
	if (func->indicationSentCb) {
		xrble_hal_gattservercallback.indicationSentCb =
			func->indicationSentCb;
	}
	if (func->mtuChangeCb) {
		xrble_hal_gattservercallback.mtuChangeCb = func->mtuChangeCb;
	}
	return 0;
}

void DATABASE_SHOW(BleGattService *srvcInfo)
{
	char uuid_str[BT_UUID_STR_LEN];
	BtUuid ohos_uuid;
	struct bt_uuid *p_uuid;

	xr_sys_debug_printf(
		"=================== OHOS GATT DATA BASE ===================\n");
	xr_sys_debug_printf("attr NUM = %d\n", srvcInfo->attrNum);
	for (int i = 0; i < srvcInfo->attrNum; i++) {
		switch (srvcInfo->attrList[i].attrType) {
		case OHOS_BLE_ATTRIB_TYPE_SERVICE:
			xr_sys_debug_printf("======primary service:\n");
			break;
		case OHOS_BLE_ATTRIB_TYPE_CHAR:
			xr_sys_debug_printf("======character:\n");
			break;
		case OHOS_BLE_ATTRIB_TYPE_CHAR_VALUE:
			xr_sys_debug_printf("======character value:\n");
			break;
		case OHOS_BLE_ATTRIB_TYPE_CHAR_CLIENT_CONFIG:
			xr_sys_debug_printf("======character client config:\n");
			break;
		case OHOS_BLE_ATTRIB_TYPE_CHAR_USER_DESCR:
			xr_sys_debug_printf("======character client config:\n");
			break;
		default:
			break;
		}

		switch (srvcInfo->attrList[i].uuidType) {
		case OHOS_UUID_TYPE_16_BIT:
			ohos_uuid.uuidLen =
				BT_UUID_SIZE_16; //todo 2or16???????? two set of api
			memcpy(ohos_uuid.uuid, srvcInfo->attrList[i].uuid,
			       ohos_uuid.uuidLen);
			break;
		case OHOS_UUID_TYPE_32_BIT:
			ohos_uuid.uuidLen = BT_UUID_SIZE_32; //todo
			memcpy(ohos_uuid.uuid, srvcInfo->attrList[i].uuid,
			       ohos_uuid.uuidLen);
			break;
		case OHOS_UUID_TYPE_128_BIT:
			ohos_uuid.uuidLen = BT_UUID_SIZE_128; //todo
			memcpy(ohos_uuid.uuid, srvcInfo->attrList[i].uuid,
			       ohos_uuid.uuidLen);
			break;
		case OHOS_UUID_TYPE_NULL:
		default:
			ohos_uuid.uuidLen = 0;
			break;
		}
		p_uuid = NULL;
		OHOS_UUID_TO_XR_UUID(&ohos_uuid, &p_uuid);
		bt_uuid_to_str(p_uuid, uuid_str, sizeof(uuid_str));
		xr_sys_debug_printf(
			"i=[%d], attr=[%p] ,uuid=[%s], perm=[0x%04x], propertiles=[0x%04x];\n",
			i, &srvcInfo->attrList[i], uuid_str,
			srvcInfo->attrList[i].permission,
			srvcInfo->attrList[i].properties);
		BT_GATT_DEINIT_UUID(&p_uuid);
		// srvcInfo->attrList[i].attrType
		// srvcInfo->attrList[i].permission
		// srvcInfo->attrList[i].uuidType
		// srvcInfo->attrList[i].uuid
		// srvcInfo->attrList[i].*value
		// srvcInfo->attrList[i].valLen
		// srvcInfo->attrList[i].properties
		// srvcInfo->attrList[i].func
	}
	xr_sys_debug_printf(
		"===========================================================\n");
	return;
}

// int DATABASE_SET(BleGattService *srvcInfo)
// {
// 	void *_read_cb = read_att_cb;
// 	void *_write_cb = write_att_cb;

// 	//获得database大小
// 	uint8_t srv_num = 1; //服务数

// 	for (int i = 0; i < srv_num; i++) { //遍历服务
// 		uplus_ble_uuid_t uplus_srv_uuid = uplus_ble_service_database->p_srv_db[i].srv_uuid;
// 		uint8_t char_num = uplus_ble_service_database->p_srv_db[i].char_num;
// 		struct bt_gatt_service *vnd_svc = NULL;
// 		if (uplus_ble_service_database->p_srv_db[i].srv_type == UPLUS_BLE_PRIMARY_SERVICE) {
// 			vnd_svc = ble_hal_add_svc(uplus_srv_uuid.uuid16, 0); // todo uuid 128 not support
// 		} else if (uplus_ble_service_database->p_srv_db[i].srv_type == UPLUS_BLE_SECONDARY_SERVICE){
// 			vnd_svc = ble_hal_add_svc(uplus_srv_uuid.uuid16, 1); // todo uuid 128 not support
// 		}
// 		for (int j = 0; j < char_num; j++) { //遍历特征
// 		uplus_ble_gatts_char_db_t uplus_ble_chr = uplus_ble_service_database->p_srv_db[i].p_char_db[j];
// 			uint16_t val_perms = BT_GATT_PERM_READ | BT_GATT_PERM_WRITE;
// 			uint8_t rd_author = uplus_ble_service_database->p_srv_db[i].p_char_db[j].rd_author;
// 			uint8_t wr_author = uplus_ble_service_database->p_srv_db[i].p_char_db[j].wr_author;
// 			if (uplus_ble_chr.char_property &  0x40) { // support auth
// 				if (rd_author) {
// 					val_perms |= BT_GATT_PERM_READ_AUTHEN;
// 				}
// 				if (wr_author) {
// 					val_perms |= BT_GATT_PERM_WRITE_AUTHEN;
// 				}
// 			}
// 			ble_hal_add_chr(vnd_svc, uplus_ble_chr.char_uuid.uuid16, uplus_ble_chr.char_property,
// 					val_perms, _read_cb, _write_cb);
// 		}
// 		bt_gatt_service_register(vnd_svc);
// 	}

// 	for (int i = 0; i < g_gatt_srv_db.srv_count; i++) { //遍历服务
// 		struct bt_gatt_service *vnd_svc = &(g_gatt_srv_db.srvs[i]);
// 		struct bt_gatt_attr *vnd_attrs = vnd_svc->attrs;
// 		uplus_ble_service_database->p_srv_db[i].srv_handle = vnd_attrs->handle;
// 		for (int j = 1; j < vnd_svc->attr_count; j++) { //遍历特征
// 			vnd_attrs++;//特征使用两个
// 			vnd_attrs++;//特征使用两个
// 			uplus_ble_service_database->p_srv_db[i].p_char_db[j-1].char_value_handle = vnd_attrs->handle; //特征值handle
// 			if (uplus_ble_service_database->p_srv_db[i].p_char_db[j-1].char_property & 0x80) { //cep
// 				vnd_attrs++;
// 			}
// 			if (uplus_ble_service_database->p_srv_db[i].p_char_db[j-1].char_property & 0x10) { //notify
// 				vnd_attrs++;
// 			}
// 		}
// 	}
// 	return 0;
// }

static inline int OHOS_EX_UUID_CHANGE(BleGattService *srvcInfo, int i,
				      struct bt_uuid **p_uuid)
{
	BtUuid ohos_uuid;
	switch (srvcInfo->attrList[i].uuidType) {
	case OHOS_UUID_TYPE_16_BIT:
		ohos_uuid.uuidLen =
			BT_UUID_SIZE_16; //todo 2or16???????? two set of api
		memcpy(ohos_uuid.uuid, srvcInfo->attrList[i].uuid,
		       ohos_uuid.uuidLen);
		break;
	case OHOS_UUID_TYPE_32_BIT:
		ohos_uuid.uuidLen = BT_UUID_SIZE_32; //todo
		memcpy(ohos_uuid.uuid, srvcInfo->attrList[i].uuid,
		       ohos_uuid.uuidLen);
		break;
	case OHOS_UUID_TYPE_128_BIT:
		ohos_uuid.uuidLen = BT_UUID_SIZE_128; //todo
		memcpy(ohos_uuid.uuid, srvcInfo->attrList[i].uuid,
		       ohos_uuid.uuidLen);
		break;
	case OHOS_UUID_TYPE_NULL:
	default:
		ohos_uuid.uuidLen = 0;
		break;
	}
	OHOS_UUID_TO_XR_UUID(&ohos_uuid, p_uuid);
	return 0;
}

int DATABASE_SET(BleGattService *srvcInfo)
{
	char uuid_str[BT_UUID_STR_LEN];
	BtUuid ohos_uuid;
	struct bt_uuid *p_uuid;

	xr_sys_debug_printf(
		"=================== OHOS GATT DATA BASE ===================\n");
	xr_sys_debug_printf("attr NUM = %d\n", srvcInfo->attrNum);
	for (int i = 0; i < srvcInfo->attrNum; i++) {
		switch (srvcInfo->attrList[i].attrType) {
		case OHOS_BLE_ATTRIB_TYPE_SERVICE:
			xr_sys_debug_printf("======primary service:\n");
			break;
		case OHOS_BLE_ATTRIB_TYPE_CHAR:
			xr_sys_debug_printf("======character:\n");
			break;
		case OHOS_BLE_ATTRIB_TYPE_CHAR_VALUE:
			xr_sys_debug_printf("======character value:\n");
			break;
		case OHOS_BLE_ATTRIB_TYPE_CHAR_CLIENT_CONFIG:
			xr_sys_debug_printf("======character client config:\n");
			break;
		case OHOS_BLE_ATTRIB_TYPE_CHAR_USER_DESCR:
			xr_sys_debug_printf("======character client config:\n");
			break;
		default:
			break;
		}

		switch (srvcInfo->attrList[i].uuidType) {
		case OHOS_UUID_TYPE_16_BIT:
			ohos_uuid.uuidLen =
				BT_UUID_SIZE_16; //todo 2or16???????? two set of api
			memcpy(ohos_uuid.uuid, srvcInfo->attrList[i].uuid,
			       ohos_uuid.uuidLen);
			break;
		case OHOS_UUID_TYPE_32_BIT:
			ohos_uuid.uuidLen = BT_UUID_SIZE_32; //todo
			memcpy(ohos_uuid.uuid, srvcInfo->attrList[i].uuid,
			       ohos_uuid.uuidLen);
			break;
		case OHOS_UUID_TYPE_128_BIT:
			ohos_uuid.uuidLen = BT_UUID_SIZE_128; //todo
			memcpy(ohos_uuid.uuid, srvcInfo->attrList[i].uuid,
			       ohos_uuid.uuidLen);
			break;
		case OHOS_UUID_TYPE_NULL:
		default:
			ohos_uuid.uuidLen = 0;
			break;
		}
		p_uuid = NULL;
		OHOS_UUID_TO_XR_UUID(&ohos_uuid, &p_uuid);
		bt_uuid_to_str(p_uuid, uuid_str, sizeof(uuid_str));
		xr_sys_debug_printf(
			"i=[%d], attr=[%p] ,uuid=[%s], perm=[0x%04x], propertiles=[0x%04x];\n",
			i, srvcInfo->attrList[i], uuid_str,
			srvcInfo->attrList[i].permission,
			srvcInfo->attrList[i].properties);
		BT_GATT_DEINIT_UUID(&p_uuid);
		// srvcInfo->attrList[i].attrType
		// srvcInfo->attrList[i].permission
		// srvcInfo->attrList[i].uuidType
		// srvcInfo->attrList[i].uuid
		// srvcInfo->attrList[i].*value
		// srvcInfo->attrList[i].valLen
		// srvcInfo->attrList[i].properties
		// srvcInfo->attrList[i].func
	}
	xr_sys_debug_printf(
		"===========================================================\n");
	return;
}

int BleGattsStartServiceEx(int *srvcHandle, BleGattService *srvcInfo)
{
	// DATABASE_SET(srvcInfo);
	return 0;
	// srvcInfo->attrNum;
	// srvcInfo->attrList;
	// DATABASE_SHOW(srvcInfo);

	// 	for (int i = 0; i < srvcInfo->attrNum; i++) {
	// 		srvcInfo->attrList[i].attrType
	// 		srvcInfo->attrList[i].permission
	// 		srvcInfo->attrList[i].uuidType
	// 		srvcInfo->attrList[i].uuid
	// 		srvcInfo->attrList[i].*value
	// 		srvcInfo->attrList[i].valLen
	// 		srvcInfo->attrList[i].properties
	// 		srvcInfo->attrList[i].func
	// 	}

	// 	switch (srvcInfo->attrList->uuidType)
	// 	{
	// 	case OHOS_UUID_TYPE_16_BIT:
	// 		break;
	// 	case OHOS_UUID_TYPE_32_BIT:
	// 		break;
	// 	case OHOS_UUID_TYPE_128_BIT:
	// 		break;
	// 	case OHOS_UUID_TYPE_NULL:
	// 	default:
	// 		break;
	// 	}

	// 	srvcInfo->attrList->uuidType;
	// 	srvcInfo->attrList->uuid;
	// 	srvcInfo->attrList->value;
	// 	srvcInfo->attrList->valLen;
	// 	srvcInfo->attrList->properties;
	// 	srvcInfo->attrList->func;

	// typedef struct {
	//     /** Attribute type */
	//     BleAttribType attrType;
	//     /** Operation permission. For details, see {@link GattAttributePermission}. */
	//     unsigned int permission;
	//     /** UUID type */
	//     UuidType uuidType;
	//     /** UUID */
	//     unsigned char uuid[OHOS_BLE_UUID_MAX_LEN];
	//     /** Data */
	//     unsigned char *value;
	//     /** Data length */
	//     unsigned char valLen;
	//     /** Property. For details, see {@link GattCharacteristicProperty}. */
	//     unsigned char properties;
	//     /** Operation callback */
	//     BleGattOperateFunc func;
	// } BleGattAttr;

	// 		err = bt_gatt_service_register(&met_svc);

	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	//todo
	return 0;
}

int BleGattsStopServiceEx(int srvcHandle)
{
	// bt_gatt_service_unregister();
	xr_sys_debug_printf("%s,%d\r\n", __func__, __LINE__);
	//todo
	return 0;
}

#endif /* CONFIG_BLEHOST */
